def deal_num(data, count=2):
    """
    将float四舍五入,保留两位小数,转为str类型
    :param count: 保留的位数
    :param data:
    :return:
    """
    return str(round(data, count)).rstrip('0').rstrip('.')


class BodyAnalysisModel:
    """
        人体成分分析各个字段对应的数据
        这里变量的声明只作为说明使用,如果要进行数据绘制,我显示的进行赋值
    """
    # weight_max = ' 84.5'  # 体重正常范围的高值
    # weight_min = ' 69.5'  # 体重正常范围的低值
    # fat_max: str  # 体重正常范围的高值
    # fat_min: str  # 体重正常范围的低值
    # bone_max: str  # 骨质正常范围的高值
    # bone_min: str  # 骨质正常范围的低值
    # protein_max = ' 22.5'  # 蛋白质正常范围的高值
    # protein_min = ' 17.5'  # 蛋白质正常范围的低值
    # water_max = ' 43.6'  # 水分正常范围的高值
    # water_min = ' 32.5'  # 水分正常范围的低值
    # muscle_max = ' 54.5'  # 肌肉正常范围的高值
    # muscle_min = ' 36.5'  # 肌肉正常范围的低值
    # SMM_max = ' 32.5'  # 骨骼肌正常范围的高值
    # SMM_min = ' 24.1'  # 骨骼肌正常范围的低值
    # PBF_max = ' 20.0'  # 体脂率正常范围的高值
    # PBF_min = ' 10.0'  # 体脂率正常范围的低值
    # BMI_max: str  # 体质指数正常范围的高值
    # BMI_min: str  # 体质指数正常范围的低值
    # WHR_max = ' 0.7'  # 腰臀比正常范围的高值
    # WHR_min = ' 0.8'  # 腰臀比正常范围的低值
    # edema_max = ' 0.3'  # 水肿系数正常范围的高值
    # edema_min = ' 0.35'  # 水肿系数正常范围的低值
    # LiverRisk = ' 65'  # 脂肪肝风险系数
    # ASMI = ' 6.5'  # 四肢骨骼肌指数
    # VFIMax: str  # 内脏脂肪指数正常范围的高值
    # VFIMin: str  # 内脏脂肪指数正常范围的低值
    # Diagnosis = ' 身体脂肪偏高 无机盐偏低 水分偏低 蛋白质偏低 骨骼肌含量偏低 身体左右均衡'  # 诊断结论(UTF - 8编码)

    weight: int  # 体重
    weight_line_text: str  # 体重划线后面的字体
    fat: float  # 脂肪 重量
    fat_per: str  # 脂肪百分比
    bone: float  # 骨质 重量
    protein: float  # 蛋白质 重量
    water: float  # 水分
    water_line_text: str  # 水分划线后面的字体
    PBF: str  # 体脂百分比
    PBF_line_text: str  # 体脂百分比,显示在划线的后面
    muscle: str  # 肌肉
    muscle_line_text: str  # 肌肉划线后面的字体
    LBM: str  # 瘦体重（去脂体重）
    ICW: str  # 细胞内液
    ECW: str  # 细胞外液
    standard_weight: str  # 目标体重
    weight_control: str  # 体重控制
    fat_control: str  # 脂肪控制量
    muscle_control: str  # 肌肉控制量
    body_age: str  # 身体年龄
    score: str  # 健康评分
    BMR: str  # 基础代谢
    WHR: str  # 腰臀比（2位小数）
    WHR_line_text: str  # 腰臀比（2位小数）划线后面字体
    edema: str  # 水肿系数（2位小数）
    BMI: str  # 体质指数
    bmi_line_text: str  # 体质指数 划线后面字体
    SMM: str  # 骨骼肌
    SMM_line_text: str  # 骨骼肌划线后面字体
    bone_per: str  # 骨质百分比
    water_per: str  # 水分百分比
    protein_per: str  # 蛋白质 百分比
    total_water: float  # 总水分重量
    type_code: int  # 体型类型 1消瘦型,2肌肉不足型,3隐性肥胖型,4低脂肪型,5健康匀称型,6脂肪过多型,7运动员型,8超重肌肉型,9肥胖型
    VFI: str  # 内脏脂肪指数
    bone_line_text: str  # 骨质划线后面的字体
    result: str  # 结论,1消瘦型,2肌肉不足型,3隐性肥胖型,4低脂肪型,5健康匀称型,6脂肪过多型,7运动员型,8超重肌肉型,9肥胖型,用于匹配体征词

    def set_test_info(self, data):
        """
        根据表 TestData 设置报告数值
        :param data:
        :return:
        """
        self.result = data[-3]
        self.SMM = round(data[20], 2)
        self.SMM_line_text = deal_num(data[20], 2)
        self.edema = round(data[24], 2)
        self.BMR = deal_num(data[23], 0)
        self.WHR = data[22]
        self.WHR_line_text = deal_num(data[22], 2)
        self.body_age = data[27]
        self.score = deal_num(data[28], 1)
        self.standard_weight = deal_num(data[15], 2)
        self.weight_control = deal_num(data[16], 2)
        self.fat_control = deal_num(data[17], 2)
        self.muscle_control = deal_num(data[18], 2)
        self.ECW = round(data[9], 2)
        self.LBM = round(data[12], 2)
        self.ICW = round(data[8], 2)
        self.muscle = round(data[11], 2)
        self.muscle_line_text = deal_num(data[11], 2)
        self.PBF = data[19]
        self.PBF_line_text = deal_num(data[19], 2)
        self.water = round(data[10], 2)
        self.water_line_text = deal_num(data[10], 2)
        self.total_water = self.water
        self.age = data[3]
        self.weight = int(data[14])
        self.weight_line_text = deal_num(data[14], 2)
        self.fat = round(data[5], 2)
        self.BMI = data[21]
        self.bmi_line_text = deal_num(data[21], 2)
        self.bone = round(data[6], 2)
        self.bone_line_text = deal_num(data[6], 2)
        self.protein = round(data[7], 2)
        self.fat_per = f'{deal_num(self.fat * 100 / self.weight, count=1)}%'
        self.bone_per = f'{deal_num(self.bone * 100 / self.weight, count=1)}%'
        self.water_per = f'{deal_num(self.water * 100 / self.weight, count=1)}%'
        self.protein_per = f'{deal_num(self.protein * 100 / self.weight, count=1)}%'
        self.type_code = int(data[-2])
        self.VFI = deal_num(data[25], 2)
        setattr(self, f'body_type_{self.type_code if self.type_code < 9 else 9}', self.type_code)

    edema_range: str  # 水肿系数（2位小数）
    BMI_level: int  # 体质指数等级 1体重较轻,2正常,3超重,4一级肥胖,5二级肥胖,6三级肥胖
    SMM_level: int  # 骨骼肌 类型 1弱,2正常,3发达
    SMM_top_level: int  # 上肢骨骼肌 类型 1弱,2正常,3发达
    SMM_bottom_level: int  # 下肢骨骼肌 类型 1弱,2正常,3发达
    SMM_balance_level: int  # 左右均衡类型 1均衡,2不均衡
    WHR_type: int  # 腰臀比类型,1梨形,2正常,3苹果
    PBF_level: int  # 体脂率评定 1低,2正常,3高
    protein_level: int  # 蛋白质 1不足,2正常
    fat_level: int  # 脂肪类型 1不足,2正常,3过量
    fat_range: str  # 脂肪正常范围
    bone_level: int  # 骨质(无机盐)等级 1不足,2正常
    protein_range: str  # 蛋白质正常范围
    bone_range: str  # 骨质(无机盐)正常范围
    water_range: str  # 水分正常范围
    weight_line_range: str  # 水分划线后面的范围
    ICW_range: str  # 细胞内液正常范围
    muscle_line_range: str  # 肌肉划线后面的范围
    bmi_per_line_range: str  # 体质指数划线后面的范围
    bone_line_range: str  # 骨质划线后面的范围
    water_line_range: str  # 水分划线后面的范围
    SMM_line_range: str  # 骨骼肌划线后面的范围
    PBF_line_range: str  # 体脂率划线后面的范围
    WHR_line_range: str  # 腰臀比划线后面的范围
    test_date: str  # 测试时间
    ECW_range: str  # 细胞外液 范围

    def set_scale(self, data, conf):
        """
        根据表TestDataScale 设置评定数据
        :param conf: 读取的json配置
        :param data:
        :return:
        """
        self.edema_range = f'[{data[15]}]'
        self.BMI_level = int(data[25])
        setattr(self, f'BMI_level_{self.BMI_level}', '√')
        self.SMM_level = int(data[31])
        setattr(self, f'SMM_level_{self.SMM_level}', '√')
        self.SMM_top_level = int(data[33])
        setattr(self, f'SMM_top_level_{self.SMM_top_level}', '√')
        self.SMM_bottom_level = int(data[34])
        setattr(self, f'SMM_bottom_level_{self.SMM_bottom_level}', '√')
        self.SMM_balance_level = int(data[35])
        setattr(self, f'SMM_balance_level_{int(self.SMM_balance_level)}', '√')
        self.WHR_type = int(data[27])
        setattr(self, f'WHRF_level_{self.WHR_type}', '√')  # 腰臀比类型
        self.PBF_level = int(data[26])
        setattr(self, f'PBF_level_{int(self.PBF_level)}', '√')
        self.protein_level = int(data[28])
        setattr(self, f'protein_level_{int(self.protein_level)}', '√')
        self.protein_range = f'[{data[5]}]'
        self.fat_level = int(data[29])
        setattr(self, f'fat_level_{int(self.fat_level)}', '√')
        self.fat_range = f'[{data[3]}]'
        self.bone_level = int(data[30])
        setattr(self, f'bone_level_{int(self.bone_level)}', '√')
        self.bone_range = f'[{data[4]}]'
        self.bone_line_range = data[4]
        self.water_range = f'[{data[8]}]'
        self.water_line_range = data[8]
        self.weight_line_range = data[8]
        self.ICW_range = f'[{data[6]}]'
        self.ECW_range = f'[{data[7]}]'
        self.muscle_line_range = data[10]
        self.bmi_per_line_range = data[13]
        self.SMM_line_range = data[12]
        self.PBF_line_range = data[11]
        self.WHR_line_range = data[14]
        self.test_date = str(data[-1].date())
        self.set_VFI(data, conf)
        self.set_PBF_line(data, conf)
        self.set_line(data, conf, 'bone_line', 19)
        self.set_line(data, conf, 'muscle_line', 17)
        self.set_line(data, conf, 'weight_line', 16)
        self.set_line(data, conf, 'water_line', 20)
        self.set_line(data, conf, 'SMM_line', 21)
        self.set_line(data, conf, 'bmi_line', 22)
        self.set_line(data, conf, 'WHR_line', 23)

    def set_line(self, data, conf, key, pos):
        """
        通用化的设置划线长度以及划线后面数值的位置,因为这里的线不是从头开始画,所以要加上前面的线长
        :param data: 数据来源
        :param conf: 配置信息
        :param key: 数值对应的配置key
        :param pos: 对应数值所在表的位置
        :return:
        """
        per_line_len = conf['per_line']
        count = data[pos]
        line = conf['pos']['lines'][key]
        setattr(self, key, tuple((line[0] + 54 + count * per_line_len, line[1])))
        conf['pos']['text'][f'{key}_text'] = [int(line[0] + count * per_line_len) + 30 + 54, line[1] - 20]

    def set_PBF_line(self, data, conf):
        """
        设置PBF体脂百分比的划线
        :param data:
        :param conf:
        :return:
        """
        per_line_len = conf['per_line']
        count = data[18]
        line = conf['pos']['lines']['PBF_line']
        setattr(self, 'PBF_line', tuple((line[0] + count * per_line_len, line[1])))
        setattr(self, 'PBF_vertical_line', '')
        conf['pos']['text']['PBF_line_text'] = [int(line[0] + count * per_line_len) + 30, line[1] - 20]

    def set_VFI(self, data, conf):
        """
        根据内脏脂肪的划线长度计算线的终点坐标,同时修改内脏脂肪text的位置
        :param data:
        :param conf:
        :return:
        """
        VFI_line_count = data[24]  # 内脏脂肪划线的长度
        VFI_line = conf['pos']['lines']['VFI_line']
        # 因为内脏脂肪是从6开始画,所以这里需要减去6
        setattr(self, 'VFI_line', tuple((VFI_line[0] + int((VFI_line_count - 6) * conf['VFI_per_line']), VFI_line[1])))
        conf['pos']['text']['VFI'][0] = VFI_line[0] + int((VFI_line_count - 6) * conf['VFI_per_line']) + 30

    TR_fat: str  # 躯干脂肪量
    LA_fat: str  # 左上肢脂肪
    RA_fat: str  # 右上肢脂肪
    LL_fat: str  # 左下肢脂肪
    RL_fat: str  # 右下肢脂肪
    TR_water: str  # 躯干水分量
    LA_water: str  # 左上肢水分
    RA_water: str  # 右上肢水分
    LL_water: str  # 左下肢水分
    RL_water: str  # 右下肢水分
    TR_muscle: str  # 躯干肌肉量
    LA_muscle: str  # 左上肢肌肉
    RA_muscle: str  # 右上肢肌肉
    LL_muscle: str  # 左下肢肌肉
    RL_muscle: str  # 右下肢肌肉
    TR_bone: str  # 躯干骨质
    LA_bone: str  # 左上肢骨质
    RA_bone: str  # 右上肢骨质
    LL_bone: str  # 左下肢骨质
    RL_bone: str  # 右下肢骨质
    TR_fat_detail: str  # 躯干脂肪,节段分析中

    def set_jieduan(self, data):
        """
        根据表TestJieDuan设置节段分析数据
        :param data:
        :return:
        """
        # 躯干数据
        self.TR_fat = deal_num(data[3])
        self.TR_fat_detail = deal_num(data[3])
        self.TR_muscle = deal_num(data[4])
        self.TR_bone = deal_num(data[5])
        self.TR_water = deal_num(data[6])

        # 左上肢数据
        self.LA_fat = deal_num(data[8])
        self.LA_muscle = deal_num(data[9])
        self.LA_bone = deal_num(data[10])
        self.LA_water = deal_num(data[11])

        # 右上肢数据
        self.RA_fat = deal_num(data[13])
        self.RA_muscle = deal_num(data[14])
        self.RA_bone = deal_num(data[15])
        self.RA_water = deal_num(data[16])

        # 左下肢数据
        self.LL_fat = deal_num(data[18])
        self.LL_muscle = deal_num(data[19])
        self.LL_bone = deal_num(data[20])
        self.LL_water = deal_num(data[21])

        # 右下肢数据
        self.RL_fat = deal_num(data[23])
        self.RL_muscle = deal_num(data[24])
        self.RL_bone = deal_num(data[25])
        self.RL_water = deal_num(data[26])

    name: str  # 姓名（UTF - 8编码）
    sex: int  # 性别 （男1，女2）
    height: str  # 身高
    age: str  # 年龄
    reg_no: str  # 体检号

    def set_info(self, data):
        """
        根据表ConnerInfo设置用户基本信息
        :param data:
        :return:
        """
        self.reg_no = data[-1]
        self.name = f'{data[-1]}/{data[1]}'
        self.sex = data[3]
        self.height = deal_num(data[-2], 1)
        if self.sex == '男':
            self.sex_man = '√'
        else:
            self.sex_woman = '√'

    # 5khz 阻抗值

    RA5: str
    LA5: str
    TR5: str
    RL5: str
    LL5: str
    # 50khz 阻抗值
    RA50: str
    LA50: str
    TR50: str
    RL50: str
    LL50: str
    # 100khz 阻抗值
    RA100: str
    LA100: str
    TR100: str
    RL100: str
    LL100: str
    # 250khz 阻抗值
    RA250: str
    LA250: str
    TR250: str
    RL250: str
    LL250: str
    # 500khz 阻抗值
    RA500: str
    LA500: str
    TR500: str
    RL500: str
    LL500: str

    def set_impedance(self, data):
        """
        设置阻抗的数值
        :param data:
        :return:
        """
        # 5khz 阻抗值
        self.RA5 = deal_num(data[3], 0)
        self.LA5 = deal_num(data[4], 0)
        self.TR5 = deal_num(data[5], 0)
        self.RL5 = deal_num(data[6], 0)
        self.LL5 = deal_num(data[7], 0)
        # 50khz 阻抗值
        self.RA50 = deal_num(data[8], 0)
        self.LA50 = deal_num(data[9], 0)
        self.TR50 = deal_num(data[10], 0)
        self.RL50 = deal_num(data[10], 0)
        self.LL50 = deal_num(data[12], 0)
        # 100khz 阻抗值
        self.RA100 = deal_num(data[13], 0)
        self.LA100 = deal_num(data[14], 0)
        self.TR100 = deal_num(data[15], 0)
        self.RL100 = deal_num(data[16], 0)
        self.LL100 = deal_num(data[17], 0)
        # 250khz 阻抗值
        self.RA250 = deal_num(data[18], 0)
        self.LA250 = deal_num(data[19], 0)
        self.TR250 = deal_num(data[20], 0)
        self.RL250 = deal_num(data[21], 0)
        self.LL250 = deal_num(data[22], 0)
        # 500khz 阻抗值
        self.RA500 = deal_num(data[23], 0)
        self.LA500 = deal_num(data[24], 0)
        self.TR500 = deal_num(data[25], 0)
        self.RL500 = deal_num(data[26], 0)
        self.LL500 = deal_num(data[27], 0)
